
import java.awt.*;
import java.io.*;
import java.util.*;

import javax.swing.*;

/**
 * The Assembler class - Converting "asm" to "bin" (Intermediate Format).
 * @author Hemant and Sandeep
 *
 */

public class Assem {
         public static String fillString(char filler, int count){
                char[] Cary = new char[count];
                while(count>0){ count--;  Cary[count] = filler ;   }
                return new String(Cary);
                }
         @SuppressWarnings("unchecked")
        public static void main(String args[]) throws IOException{
                 
                Vector<Vector<String>> vector1 = new Vector<Vector<String>>();
                Vector<String> vector2 = new Vector<String>();
                Vector<String> vector3 ;
                int m=0;
                String[] label = new String [50] ;
                BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\Hemanth\\Desktop\\assemblerout.txt"));
                //String[] Str1 = new String [10];
                Scanner s = null;
                String[] jumpaddr = new String[50];
                // Forming the Key Value pairs by using a Hasp-map, we can also use a Hash-table here!!      
        Hashtable<String, String> ht = new Hashtable<String,String>();
       
    // forming the Key value pairs for the Instructions both R-type and I-type
   
    ht.put("add","100000");
    ht.put("sub","100010");
    ht.put("load","100011");
    ht.put("Store","101011");
    ht.put("bez","000100");
    ht.put("addi","001000");
    // forming the key value pairs for the registers
   
    ht.put("r0", "00000");
    ht.put("r1", "00001");
    ht.put("r2", "00010");
    ht.put("r3", "00011");
    ht.put("r4", "00100");
    ht.put("r5", "00101");
    ht.put("r6", "00110");
    ht.put("r7", "00111");
    ht.put("r8", "01000");
    ht.put("r9", "01001");
    ht.put("r10", "01010");
    ht.put("r11", "01011");
    ht.put("r12", "01100");
    ht.put("r13", "01101");
    ht.put("r14", "01110");
    ht.put("r15", "01111");
    ht.put("r16", "10000");
    ht.put("r17", "10001");
    ht.put("r18", "10010");
    ht.put("r19", "10011");
    ht.put("r20", "10100");
    ht.put("r21", "10101");
    ht.put("r22", "10110");
    ht.put("r23", "10111");
    ht.put("r24", "11000");
    ht.put("r25", "11001");
    ht.put("r26", "11010");
    ht.put("r27", "11011");
    ht.put("r28", "11100");
    ht.put("r29", "11101");
    ht.put("r30", "11110");
    ht.put("r31", "11111");
                File file = new File("C:\\Users\\Hemanth\\Desktop\\example.txt");
                Scanner scanner = null;
                try {
                        scanner = new Scanner(file);
                } catch(FileNotFoundException e) {
                        System.out.println("file not found: " + e.getMessage());
                }
                while(scanner.hasNextLine()) {
                        String line = scanner.nextLine();
                        vector2.addElement(line);
   
                }
                scanner.close();

                System.out.println("Vector2 Size " + vector2.size());

                for(int j = 0; j < vector2.size(); j++)
                {
                         
                        vector3 = new Vector() ;
                        s = new Scanner(vector2.get(j));
                        s.useDelimiter("\\s*,*\\s");
                                                while(s.hasNext())
                        {
                                vector3.addElement(s.next());
                               
                        }
                       
                        vector1.addElement(vector3);
                }
               

                
 /* m stores the no of branch statements and array label stores the all the
  *   labels found in the input in the following code.             
  */
                
                for (int n=0; n<vector1.size(); n++)
               { int k=0;
               String bez = "bez" ;
                 if(((vector1.get(n)).get(0)).equals(bez))
                  {
                 
                    m++;
                   k=(vector1.get(n)).size();
                   label[m] = (vector1.get(n)).get(k-1);
                                   }
                 
                 
                }

 /* suppose this is the input
  *  bez r1,r2, done
  * add  r1,r2,r3
  * done: add r4,r5,r4                                  
  * the following code stores the relative position of "done:" with respect to bez  
  * and stores it in count.  in this example, count = 2
  * O/P = bez r1, done
  *       add  r1,r2,r3
  *       add r4,r5,r4   (the " done:") is removed .
  */
                
                
                
                
                
                for (int k=1; k<=m; k++)    
        {
         for (int n=0; n<vector1.size(); n++)
               
          {    int j=(vector1.get(n)).size();
               String lab = label[k] + ":" ;  
               
             if(j>0)
             {      
               if((vector1.get(n)).get(j-1).equals(label[k]))
             
                 {  int count =1;
                 
                   while((n+count)<vector1.size())
                   {   if((vector1.get(n +count)).get(0).equals(lab))
                      {  
                    	  String temp = (Integer.toBinaryString(count)) ;
                          
                         jumpaddr[k] = fillString('0',16-temp.length()) + temp; // forming the immediate value(16 bits)
                          (vector1.get(n +count)).remove(0);
                      }      
            	     count++;
                   } 
            	                            
                 }
             }               
              
               // j++;
           }      
          }  
/* the following code checks for bez statement, and converts the label into the binary
* equivalent of the relative position of the target.
* eg: I/P  bez r1, done     O/P : bez r1, binary(2)
*           add  r1,r2,r3             add  r1,r2,r3    
*            add r4,r5,r4              add r4,r5,r4  (this was the target address)
*/
    
                String bez = "bez" ;
                
                for (int p=1; p<=m; p++)
           
        {  
           for (int n=0; n<vector1.size(); n++)
           { int j=(vector1.get(n)).size();
             
           
              if(j>0) 
              {  
            	  if((vector1.get(n)).get(0).equals(bez))
                  {   
                
                 
                     (vector1.get(n)).remove(j-1);
                    (vector1.get(n)).add(jumpaddr[p]);
                    ht.put((vector1.get(n)).get(j-1),(vector1.get(n)).get(j-1));
                   }
              }               
              
               
            }
        }
               
                
                
                
             for(int n=0; n<vector1.size(); n++)
              {  int j=(vector1.get(n)).size() ;
                   String load = "load" ;
                   String store = "store" ;
                   
                if(j>0)
                 {		   
                   if((vector1.get(n)).get(0).equals(load)||(vector1.get(n)).get(0).equals(store))            
                     {   
                	          
                             
                      for(int r=0; r<(vector1.get(n)).get(j-1).length();r++ )
                      {  
                        if((vector1.get(n)).get(j-1).charAt(r)=='(')
                         {  String no = (vector1.get(n)).get(j-1).substring(0,r);
                            System.out.println("the value of no"+ no);
                            String reg = (vector1.get(n)).get(j-1).substring(r+1,((vector1.get(n)).get(j-1).length())-1) ;
                            (vector1.get(n)).remove(j-1);
                            (vector1.get(n)).add(reg);
                            System.out.println("the length of the string" + (vector1.get(n)).toString().length());
                            System.out.println("vector 1 line = " +(vector1.get(n)).toString() );
                            System.out.println("the value of reg "  +reg);
                              int temp = Integer.parseInt(no);
                              String offset = Integer.toBinaryString(temp);
                              offset = fillString('0',16-offset.length()) + offset ;
                              (vector1.get(n)).add(offset);
                              ht.put((vector1.get(n)).get(j),(vector1.get(n)).get(j));
                          }
                       }  
                     }
                  }  
              }
                  
             
             
             
            for(int n=0; n<vector1.size(); n++)
            {   int q = 0;
                   String addi = "addi" ;
             if((vector1.get(n)).size()>1)
                {
            	  if((vector1.get(n)).get(0).equals(addi) || (vector1.get(n)).get(1).equals(addi))
                   { q= (vector1.get(n)).size();
                   String noimm = (vector1.get(n)).get(q-1) ;
                    int temp = Integer.parseInt(noimm);
                    String immvalue = Integer.toBinaryString(temp);
                    System.out.println("the value of immediate value"+ immvalue);  
                    immvalue = fillString('0',16-immvalue.length()) + immvalue ;
                    (vector1.get(n)).remove(q-1);
                    (vector1.get(n)).add(immvalue);
                    ht.put((vector1.get(n)).get(q-1),(vector1.get(n)).get(q-1));
                    }
                }               
            	  
            	  
             }
                 
                  
                 
 /* converting the code into corresponding binary value and writting into output file 
  *  assemblerout.txt in the std MIPS format                 
  */
                  for(int n=0; n<vector1.size(); n++)
                 { 
                	   int j=(vector1.get(n)).size();
                	   String line = "";
                       String k ="";
    
                       
             if(j>1)  // checking if the line contains only label           
             { 	   
                   //Assuming that all reg names start with the letter 'r' and 
                   //the last 3 words in a R type Instruc are all reg's
          
            	 
            	 if((vector1.get(n)).get(j-1).charAt(0)=='r' & 
                       (vector1.get(n)).get(j-2).charAt(0)=='r' & (vector1.get(n)).get(j-3).charAt(0)=='r' )
                           // Instruction is R type            	  
                	  
                     {   
                        String reg =ht.get((vector1.get(n)).get(j-2)) +ht.get((vector1.get(n)).get(j-1))+ ht.get((vector1.get(n)).get(j-3));
                	  
                	  
                    line= "000000" + reg + "00000" + ht.get((vector1.get(n)).get(j-4));
                 
                      }
                  
                     else
                	// Instruction is I type
                    {
                	    int i=j;
                	  while(i>0)  
                  
                       {   if((vector1.get(n)).get(i-1).charAt(0)=='r')
                    	    k = k + ht.get((vector1.get(n)).get(i-1)) ;
                		     
                            i--;
                		
                       }
                	
  /*Assume that the value 0 is always stored in reg 15 (r15). hence the source reg for beq 
   *   is 15 = "01111" .. hence the O/P binary is in MIPS form (using beq instead of bez)            	  
   */
                	  
                	   if((vector1.get(n)).get(0).equals(bez))
                		 line = ht.get((vector1.get(n)).get(0)) + "01111" + k + ht.get((vector1.get(n)).get(j-1)) ;
                	   else
                	     line = ht.get((vector1.get(n)).get(0)) + k + ht.get((vector1.get(n)).get(j-1)); 
                		
                	
                	
                  }
                	
             } // checking for only label  	
                   
              else      
               {      
                 line = fillString('0',32);
               }    
             
              //line = n + " " + line + fillString('0',32-line.length()) + "  " + vector2.get(n) ;
                 
                  line = n + " " + line + "  " + vector2.get(n) ;
                      out.write(line);
                  out.newLine();
                 
                    }
                  out.close();
               


        }

       
}
